package org.opens.service.impl;

import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.opens.dao.PersonDao;
import org.opens.entity.Person;
import org.opens.service.MethodLogService;
import org.opens.service.PersonService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * @Date 2021/2/1 19:42
 * @Created by 99126
 */
@Service(value = "personService")
@Slf4j
public class PersonServiceImpl implements PersonService, ApplicationContextAware {

    @Autowired
    private PersonDao personDao;

    @Autowired
    private MethodLogService methodLogService;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void save(Person person) {
        Assert.notNull(person, "保存对象不能为null");
        personDao.insert(person);
    }

    @Transactional
    @Override
    public void deleteById(Integer id) {
        Assert.notNull(id, "id不能为null");
        personDao.deleteById(id);
        if (id == 1) {
            throw new RuntimeException("主动触发异常");
        }
    }

    @Override
    public Optional<Person> findById(Integer id) {
        Assert.notNull(id, "id不能为null");
        return Optional.ofNullable(personDao.selectById(id));
    }

    @Override
    public Person updateById(Person person) {
        Assert.notNull(person, "更新对象不能为null");
        Assert.notNull(person.getId(), "id不能为null");
        personDao.updateById(person);
        return person;
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.NESTED)
    @Override
    public int insertByRequiredFail(Person person) {
        if (person.getAge() == 66) {
            throw new RuntimeException("发生自定义异常");
        }
        return personDao.insert(person);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    @Override
    public int batchInsertByRequiredFail(List<Person> personList) {
        int count = 0;
        // 处理自调用失效
        PersonService personService = applicationContext.getBean("personService", PersonService.class);
        // personService.ageIncByREQUIRED(1);
        Person person1 = personDao.selectById(1);
        person1.setAge(person1.getAge() + 1);
        personDao.updateById(person1);
        for (Person person : personList) {
            try {
                personService.insertByRequiredFail(person);
            } catch (Exception e) {
                e.printStackTrace();
            }
            count += 1;
        }
        if (personList.size() > 3) {
            throw new RuntimeException("外层异常发生");
        }
        return count;
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    @Override
    public int ageIncByREQUIRED(int id) {
        Person person1 = personDao.selectById(id);
        person1.setAge(person1.getAge() + 1);
        int i = personDao.updateById(person1);
        /*if (id == 1) {
            throw new RuntimeException("触发异常");
        }*/
        return i;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBeforeInserting() {
        // 先插入一条id_card=123,id=1的数据
        int deleteRows = personDao.deleteById(1);
        log.info("删除影响行: " + deleteRows);

        Person person = personDao.selectById(1);
        log.info("删除后, 根据id查到的对象: " + person);

        Person person1 = new Person();
        person1.setIdCard("123");
        int insertRows = personDao.insert(person1);
        log.info("最后, 进行插入测试: " + insertRows);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertAndRecordLog(Person person) {
        personDao.insert(person);

        methodLogService.nonTransactionalInsertion("insertAndRecordLog");

        throw new RuntimeException("主动出发运行时异常");
    }

    @Override
    @Transactional
    public void insertAndSelect(Person person) {
        List<Person> peopleList1 = personDao.selectList(null);
        System.out.println(peopleList1);

        personDao.insert(person);

        List<Person> peopleList2 = personDao.selectList(null);
        System.out.println(peopleList2);
    }
}
